(function(global, factory) {
  // 通用模块导出方案 
  if (typeof exports === 'object' && typeof module !== 'undefined') {
    module.exports  = factory();
  } else if (typeof define === 'function' && define.amd)  {
    define(factory);
  } else {
    global.weCropper  = factory();
  }
}(this, (function() {
  'use strict';
  
  // ================= 默认配置 =================
  const DEFAULT = {
    id: 'default_wecropper_canvas',  // 默认安全ID
    targetId: 'target_canvas',
    pixelRatio: 1,
    width: null,
    height: null,
    scale: 2.5,
    zoom: 8,
    cut: {
      x: 0,
      y: 0,
      width: 300,  // 默认裁剪尺寸
      height: 300,
      ratio: 1
    },
    bound: 10,
    maxScale: 3,
    minScale: 0.5,
    quality: 1,
    original: false,
    full: false,
    outputType: 'png',
    fileType: '',
    rotate: 0,
    // 回调函数默认实现 
    onReady: function() {},
    onBeforeImageLoad: function() {},
    onImageLoad: function() {},
    onBeforeDraw: function(ctx, instance) {}
  };
 
  // ================= 核心类 ================= 
  function weCropper(options = {}) {
    // 参数安全验证 
    if (typeof options !== 'object' || options === null) {
      console.warn('[weCropper]  参数类型错误，已重置为空对象');
      options = {};
    }
    
    // 深度合并配置（重点修复区域）
    this.options  = {
      ...DEFAULT,
      ...options,
      // 关键参数保护 
      id: options.id  || DEFAULT.id, 
      cut: {
        ...DEFAULT.cut, 
        ...(options.cut  || {}),
        // 确保裁剪尺寸有效 
        width: options.cut?.width  || DEFAULT.cut.width, 
        height: options.cut?.height  || DEFAULT.cut.height  
      }
    };
    
    // 环境检测（兼容uni-app和微信小程序）
    const env = typeof uni !== 'undefined' ? uni : 
                typeof wx !== 'undefined' ? wx : null;
                
    if (!env) {
      throw new Error('未检测到小程序环境');
    }
 
    // 创建画布上下文（核心修复点）
    if (!this.options.id)  {
      console.error('[weCropper]  未检测到有效canvas ID，使用默认ID');
      this.options.id  = DEFAULT.id; 
    }
    
    try {
      this.ctx  = env.createCanvasContext(this.options.id,  this);
    } catch (e) {
      console.error(` 创建画布上下文失败: ${e.message}`); 
      throw new Error('Canvas初始化失败');
    }
 
    // =============== 状态初始化 ===============
    this.width  = this.options.width; 
    this.height  = this.options.height; 
    this.scale  = this.options.scale; 
    this.oldScale  = 1;
    this.rotate  = this.options.rotate; 
    this.cut  = this.options.cut; 
    this.maxScale  = this.options.maxScale; 
    this.minScale  = this.options.minScale; 
    this.quality  = this.options.quality; 
    this.original  = this.options.original; 
    this.full  = this.options.full; 
    this.outputType  = this.options.outputType; 
    this.fileType  = this.options.fileType; 
    this.bound  = this.options.bound; 
    this.pixelRatio  = this.options.pixelRatio; 
    
    // 图片相关状态 
    this.image  = null;
    this.imageInfo  = null;
    
    // 触摸状态
    this.startX  = 0;
    this.startY  = 0;
    this.originX  = 0;
    this.originY  = 0;
    this.offsetX  = 0;
    this.offsetY  = 0;
    
    // 功能标志 
    this.ready  = false;
    this.loading  = false;
    this.touching  = false;
    this.moving  = false;
    this.zooming  = false;
    this.rotating  = false;
 
    // 初始化
    this._initEvent();
    this._initCanvas();
  }
 
  // ================= 原型方法 =================
  weCropper.prototype  = {
    // 初始化事件绑定 
    _initEvent: function() {
      // 实际项目中应实现触摸事件处理
      // 示例：this._bindTouchEvents();
    },
    
    // 初始化画布（关键安全增强）
    _initCanvas: function() {
      const env = typeof uni !== 'undefined' ? uni : wx;
      
      if (!env.createSelectorQuery)  {
        console.error(' 环境不支持createSelectorQuery');
        return;
      }
      
      const query = env.createSelectorQuery(); 
      query.select(`#${this.options.id}`) 
        .boundingClientRect((rect) => {
          if (!rect || rect.width  === 0 || rect.height  === 0) {
            console.error(` 找不到canvas元素或尺寸无效: #${this.options.id}`); 
            console.warn(' 使用默认尺寸300x300');
            
            // 降级处理 
            this.width  = this.options.width  || 300;
            this.height  = this.options.height  || 300;
            
            // 设置安全尺寸
            this.ctx.canvas.width  = this.width  * this.pixelRatio; 
            this.ctx.canvas.height  = this.height  * this.pixelRatio; 
            this.ctx.scale(this.pixelRatio,  this.pixelRatio); 
          } else {
            // 正常设置 
            this.width  = this.options.width  || rect.width; 
            this.height  = this.options.height  || rect.height; 
            this.ctx.canvas.width  = this.width  * this.pixelRatio; 
            this.ctx.canvas.height  = this.height  * this.pixelRatio; 
            this.ctx.scale(this.pixelRatio,  this.pixelRatio); 
          }
          
          this.ready  = true;
          
          // 加载初始图片
          if (this.options.src)  {
            this.pushOrign(this.options.src); 
          } else if (typeof this.options.onReady  === 'function') {
            this.options.onReady(this); 
          }
        })
        .exec();
    },
    
    // 加载图片（增强错误处理）
    pushOrign: function(src) {
      if (!src) {
        console.warn('pushOrign:  缺少图片路径');
        return;
      }
      
      this.loading  = true;
      const env = typeof uni !== 'undefined' ? uni : wx;
      const that = this;
      
      // 触发加载前回调
      if (typeof this.options.onBeforeImageLoad  === 'function') {
        this.options.onBeforeImageLoad(); 
      }
      
      // 获取图片信息 
      env.getImageInfo({ 
        src: src,
        success: function(res) {
          that.imageInfo  = res;
          that.image  = res.path; 
          that.loading  = false;
          
          // 触发加载完成回调 
          if (typeof that.options.onImageLoad  === 'function') {
            that.options.onImageLoad(that); 
          }
          
          that.draw(); 
        },
        fail: function(err) {
          console.error(' 图片加载失败:', err);
          that.loading  = false;
          // 可以考虑重试机制或默认图片
        }
      });
    },
    
    // 核心绘制函数（多重安全校验）
    draw: function() {
      // 前置条件检查
      if (!this.ready)  {
        console.warn('draw:  画布未就绪');
        return;
      }
      
      if (!this.image)  {
        console.warn('draw:  无有效图片');
        return;
      }
      
      try {
        // 绘制前回调 
        if (typeof this.options.onBeforeDraw  === 'function') {
          this.options.onBeforeDraw(this.ctx,  this);
        }
        
        // 清除画布 
        this.ctx.clearRect(0,  0, this.width,  this.height); 
        
        // ===== 核心绘制逻辑 =====
        // 1. 计算图片位置和尺寸 
        const scale = this.scale; 
        const rotate = this.rotate; 
        const imgWidth = this.imageInfo.width  * scale;
        const imgHeight = this.imageInfo.height  * scale;
        const offsetX = this.offsetX; 
        const offsetY = this.offsetY; 
        
        // 2. 保存当前状态
        this.ctx.save(); 
        
        // 3. 设置原点为画布中心
        this.ctx.translate(this.width  / 2, this.height  / 2);
        
        // 4. 应用旋转
        this.ctx.rotate((rotate  * Math.PI) / 180);
        
        // 5. 绘制图片 
        this.ctx.drawImage( 
          this.image, 
          offsetX - imgWidth / 2,
          offsetY - imgHeight / 2,
          imgWidth,
          imgHeight
        );
        
        // 6. 恢复状态 
        this.ctx.restore(); 
        
        // ===== 绘制裁剪框 =====
        this._drawClipBox();
        
        // 提交绘制
        this.ctx.draw(true); 
      } catch (e) {
        console.error(' 绘制过程中出错:', e);
        // 可添加错误上报逻辑 
      }
    },
    
    // 绘制裁剪框 
    _drawClipBox: function() {
      const cut = this.cut; 
      if (!cut || !cut.width  || !cut.height)  return;
      
      // 绘制半透明遮罩
      this.ctx.fillStyle  = 'rgba(0,0,0,0.5)';
      this.ctx.fillRect(0,  0, this.width,  this.height); 
      
      // 清除裁剪区域
      this.ctx.clearRect(cut.x,  cut.y, cut.width,  cut.height); 
      
      // 绘制裁剪框边框
      this.ctx.setStrokeStyle('#FFFFFF'); 
      this.ctx.setLineWidth(2); 
      this.ctx.strokeRect(cut.x,  cut.y, cut.width,  cut.height); 
      
      // 绘制角标 
      const cornerSize = 20;
      this.ctx.setLineWidth(3); 
      this.ctx.beginPath(); 
      
      // 左上角 
      this.ctx.moveTo(cut.x,  cut.y + cornerSize);
      this.ctx.lineTo(cut.x,  cut.y);
      this.ctx.lineTo(cut.x  + cornerSize, cut.y);
      
      // 右上角 
      this.ctx.moveTo(cut.x  + cut.width  - cornerSize, cut.y);
      this.ctx.lineTo(cut.x  + cut.width,  cut.y);
      this.ctx.lineTo(cut.x  + cut.width,  cut.y + cornerSize);
      
      // 右下角
      this.ctx.moveTo(cut.x  + cut.width,  cut.y + cut.height  - cornerSize);
      this.ctx.lineTo(cut.x  + cut.width,  cut.y + cut.height); 
      this.ctx.lineTo(cut.x  + cut.width  - cornerSize, cut.y + cut.height); 
      
      // 左下角
      this.ctx.moveTo(cut.x  + cornerSize, cut.y + cut.height); 
      this.ctx.lineTo(cut.x,  cut.y + cut.height); 
      this.ctx.lineTo(cut.x,  cut.y + cut.height  - cornerSize);
      
      this.ctx.stroke(); 
    },
    
    // ============== 主要功能方法 ==============
    // 执行裁剪
    crop: function(callback) {
      if (!this.ready  || !this.image)  {
        console.warn(' 无法执行裁剪：画布未就绪或无图片');
        if (typeof callback === 'function') {
          callback({ error: 'invalid_state' });
        }
        return;
      }
      
      const env = typeof uni !== 'undefined' ? uni : wx;
      const cut = this.cut; 
      
      // 计算实际裁剪区域（考虑缩放和旋转）
      const scale = this.scale; 
      const imgWidth = this.imageInfo.width  * scale;
      const imgHeight = this.imageInfo.height  * scale;
      
      // 创建临时canvas
      env.canvasToTempFilePath({ 
        x: cut.x,
        y: cut.y,
        width: cut.width, 
        height: cut.height, 
        destWidth: cut.width  * this.pixelRatio, 
        destHeight: cut.height  * this.pixelRatio, 
        canvasId: this.options.id, 
        fileType: this.options.outputType, 
        quality: this.options.quality, 
        success: (res) => {
          if (typeof callback === 'function') {
            callback({ path: res.tempFilePath  });
          }
        },
        fail: (err) => {
          console.error(' 裁剪失败:', err);
          if (typeof callback === 'function') {
            callback({ error: 'crop_failed' });
          }
        }
      }, this);
    },
    
    // 旋转图片
    rotate: function(angle = 90) {
      if (this.loading)  return;
      
      this.rotate  += angle;
      if (this.rotate  >= 360) this.rotate  -= 360;
      else if (this.rotate  < 0) this.rotate  += 360;
      
      this.draw(); 
    },
    
    // 缩放图片 
    zoom: function(scaleFactor) {
      if (this.loading)  return;
      
      const newScale = this.scale  * scaleFactor;
      
      // 限制缩放范围 
      if (this.maxScale  && newScale > this.maxScale)  {
        this.scale  = this.maxScale; 
      } else if (this.minScale  && newScale < this.minScale)  {
        this.scale  = this.minScale; 
      } else {
        this.scale  = newScale;
      }
      
      this.draw(); 
    },
    
    // 移动图片
    move: function(deltaX, deltaY) {
      if (this.loading  || !this.imageMovable)  return;
      
      this.offsetX  += deltaX;
      this.offsetY  += deltaY;
      
      // 边界检查 
      const imgWidth = this.imageInfo.width  * this.scale; 
      const imgHeight = this.imageInfo.height  * this.scale; 
      const maxOffsetX = (imgWidth - this.cut.width)  / 2;
      const maxOffsetY = (imgHeight - this.cut.height)  / 2;
      
      if (Math.abs(this.offsetX)  > maxOffsetX) {
        this.offsetX  = this.offsetX  > 0 ? maxOffsetX : -maxOffsetX;
      }
      
      if (Math.abs(this.offsetY)  > maxOffsetY) {
        this.offsetY  = this.offsetY  > 0 ? maxOffsetY : -maxOffsetY;
      }
      
      this.draw(); 
    },
    
    // 更新配置 
    updateOptions: function(newOptions) {
      if (typeof newOptions !== 'object' || newOptions === null) {
        console.warn('updateOptions:  无效参数');
        return;
      }
      
      // 安全合并配置 
      this.options  = {
        ...this.options, 
        ...newOptions,
        id: this.options.id,   // ID不可更改 
        cut: {
          ...this.options.cut, 
          ...(newOptions.cut  || {})
        }
      };
      
      // 重新初始化 
      if (newOptions.src  && newOptions.src  !== this.options.src)  {
        this.pushOrign(newOptions.src); 
      } else {
        this.draw(); 
      }
    }
  };
 
  return weCropper;
})));